package com.sysd.filter;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.sysd.bean.Config;
import com.sysd.constant.UserRedisKeyConstant;
import com.sysd.entity.CodeMsg;
import com.sysd.entity.LoginUser;
import com.sysd.entity.Result;
import com.sysd.utils.ResponseUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Objects;

/**
 * @description: 全局校验
 * @author: bsh
 * @date: 2025/5/30 13:31
 */
@Component
public class TokenValidFilter extends AbstractGatewayFilterFactory<Config> {
    private final StringRedisTemplate stringRedisTemplate;

    @Value("${config.gateway.key}")
    public String gatewayKey;

    public TokenValidFilter(StringRedisTemplate stringRedisTemplate) {
        super(Config.class);
        this.stringRedisTemplate = stringRedisTemplate;
    }

    @Override
    public GatewayFilter apply(Config config) {
        return (exchange, chain) -> {
            ServerHttpRequest request = exchange.getRequest();
            String requestPath = request.getPath().toString();
            String requestMethod = Objects.requireNonNull(request.getMethod()).name();
            if (!isPathInWhiteList(requestPath, requestMethod, config.getWhitePathList())) {
                //拿到token后去redis里面找需要的用户信息找到后自行构建请求
                String token = request.getHeaders().getFirst("token");
                String userInfo=stringRedisTemplate.opsForValue().get(String.format(UserRedisKeyConstant.USER_LOGIN_KEY, token));
               //确实拿到数据了那么就可以去解析然后构建好数据给微服务使用了，免得服务那边还需要再查询一下
                if (!StrUtil.isEmpty(userInfo)) {
                    LoginUser loginUser = JSON.parseObject(userInfo, LoginUser.class);
                    ServerHttpRequest.Builder mutate = request.mutate();
                    mutate.header("gatewayKey", gatewayKey);
                    mutate.header("userId", loginUser.getUserId().toString());
                    mutate.header("token", token);
                    return chain.filter(exchange.mutate().request(mutate.build()).build());
                }
            }
            //后面的拦截返回错误的状态码
            ServerHttpResponse response = exchange.getResponse();
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return ResponseUtil.result(Result.error(CodeMsg.LOGIN_ERROR), exchange);
        };
    }
    private boolean isPathInWhiteList(String requestPath, String requestMethod, List<String> whitePathList) {
        return (!CollectionUtils.isEmpty(whitePathList) && whitePathList.stream().anyMatch(requestPath::startsWith)) || (Objects.equals(requestPath, "/api/short-link/admin/v1/user") && Objects.equals(requestMethod, "POST"));
    }
}
